<template>
  <a-card :bordered="false" :style="{ minHeight: `${layoutContentHeight - pageHeaderHeight - layoutFooterHeight}px` }">
    <a-card class="card" :bordered="false">
      <a-form :form="form">
        <a-form-item
          :label="$t('authenticationCenter.role.roleName')"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          v-bind="validator.nameValidProps"
        >
          <s-input
            v-decorator="[
              'name',
              {
                rules: [
                  {
                    required: true,
                    message: $t('common.emptyErr', { name: $t('authenticationCenter.role.roleName') }),
                    whitespace: true
                  },
                  {
                    validator: validator.nameValidator
                  }
                ]
              }
            ]"
            :limit="16"
          />
        </a-form-item>
        <a-form-item :label="$t('common.status')" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-select v-decorator="['status']">
            <a-select-option :value="1">{{ $t('common.inUse') }}</a-select-option>
            <a-select-option :value="2">{{ $t('common.disable') }}</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item :label="$t('common.comment')" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <s-textarea v-decorator="['comment']" :limit="120" />
        </a-form-item>
      </a-form>
    </a-card>
    <a-card class="card" :title="$t('authenticationCenter.role.permissionInfo')" :bordered="false">
      <a-table
        ref="table"
        size="default"
        rowKey="id"
        :columns="columns"
        :dataSource="tableData"
        :pagination="false"
        :expandedRows="expandedRows"
        @expandedRowsChange="handleExpand"
      >
        <template slot="menuTitle" slot-scope="text">
          {{ $t(text) }}
        </template>
        <span slot="actions" slot-scope="actions, record">
          <a-checkbox
            v-for="action in actions"
            :key="action.id"
            :checked="action.access"
            :disabled="action.disabled"
            @change="e => handleActionChange(e, record, action)"
            >{{ $t(action.name) }}</a-checkbox
          >
        </span>
      </a-table>
    </a-card>

    <!-- fixed footer toolbar -->
    <footer-tool-bar>
      <a-button v-action:add type="primary" @click="handleSubmit" :loading="confirmLoading">{{
        $t('button.save')
      }}</a-button>
    </footer-tool-bar>
  </a-card>
</template>

<script>
import cloneDeep from 'lodash/cloneDeep';
import FooterToolBar from '@/components/FooterToolbar';
import { SInput, STextarea } from '@/components';
import {
  getRole,
  getRolePerms,
  getRolePermsById,
  createRole,
  updateRole,
  validateRoleField
} from '@/api/authenticationCenter/config/role';
import { asyncValidateMixin, layoutMixin } from '@/utils/mixin';
import { breadFirstTree } from '@/utils/util';

export default {
  name: 'RoleForm',
  components: {
    FooterToolBar,
    SInput,
    STextarea
  },
  mixins: [layoutMixin, asyncValidateMixin],
  data() {
    return {
      labelCol: {
        lg: {
          span: 7
        },
        sm: {
          span: 7
        }
      },
      wrapperCol: {
        lg: {
          span: 10
        },
        sm: {
          span: 17
        }
      },

      id: 0,
      formType: 1, // 1-创建 2-编辑
      confirmLoading: false,
      form: this.$form.createForm(this),
      // 表头
      columns: [
        {
          title: this.$t('authenticationCenter.menu.title'),
          dataIndex: 'title',
          scopedSlots: {
            customRender: 'menuTitle'
          },
          width: '400px'
        },
        {
          title: this.$t('authenticationCenter.role.operablePermission'),
          dataIndex: 'actions',
          scopedSlots: {
            customRender: 'actions'
          }
        }
      ],
      originData: [], // 未把hidden为true过滤的原始路由表
      tableData: [], // 过滤之后的路由表
      expandedRows: [],
      appId: 0
    };
  },
  mounted() {
    const { id } = this.$route.params;
    if (id) {
      this.formType = 2;
      this.id = id;
      getRole({
        id
      }).then(res => {
        this.form.setFieldsValue(res.data);
      });
      getRolePermsById({
        id
      }).then(res => {
        const { data } = res;
        this.originData = cloneDeep(data);
        this.routersFilter(data);
        this.tableData = data;
        this.initExpandedRows(data);
      });
    } else {
      this.formType = 1;
      this.form.setFieldsValue({
        name: '',
        status: 1,
        comment: ''
      });
      getRolePerms({
        appId: this.appId
      }).then(res => {
        const { data } = res;
        this.originData = cloneDeep(data);
        this.routersFilter(data);
        this.tableData = data;
        this.initExpandedRows(data);
      });
    }

    this.$_asyncValidateMixin_init([
      {
        fieldName: 'name',
        caller: validateRoleField,
        extraParams: {
          id: this.id,
          appId: this.appId,
          key: 'name'
        }
      }
    ]);
  },
  methods: {
    /**
     * 初始化时将列全部展开
     */
    initExpandedRows(tree) {
      const rows = [];
      breadFirstTree(
        tree,
        jn => {
          if (Array.isArray(jn.children) && jn.children.length > 0) {
            rows.push(jn.id);
          }
          return true;
        },
        // eslint-disable-next-line
        'children'
      );
      this.expandedRows = rows;
    },
    /**
     * 将隐式路由过滤
     * @param routers 完整路由
     */
    routersFilter(routers) {
      try {
        breadFirstTree(
          routers,
          jn => {
            if (jn.meta) {
              const meta = JSON.parse(jn.meta);
              if (meta.alwaysAccess) {
                jn.actions = jn.actions.map(ele => {
                  ele.access = true;
                  ele.disabled = true;
                  return ele;
                });
              }
            }
            if (!!jn.children && Array.isArray(jn.children)) {
              jn.children = jn.children.filter(ele => {
                // eslint-disable-next-line
                const meta = ele.meta || '{}';
                // const { hidden } = JSON.parse(meta);
                // return ele.hasOwnProperty('children') || !hidden;
                return Object.hasOwnProperty.call(ele, 'children') || Object.hasOwnProperty.call(ele, 'actions'); // 系统设置里的系统配置只有终极管理员才能用，所以要过滤掉;
              });
            }
            return true;
          },
          // eslint-disable-next-line
          'children'
        );
      } catch (err) {
        // todo
      }
    },

    /**
     * 展开回调
     */
    handleExpand(expandedRows) {
      this.expandedRows = expandedRows;
    },

    /**
     * action勾选变化回调
     */
    handleActionChange(e, record, act) {
      const data = cloneDeep(this.tableData);
      breadFirstTree(
        data,
        jn => {
          if (jn.id === record.id) {
            if (!!jn.actions && Array.isArray(jn.actions)) {
              // 如果没权限查看，则也没权限增删改等等
              if (act.action === 'view' && act.access) {
                jn.actions = jn.actions.map(ele => {
                  ele.access = false;
                  return ele;
                });
              } else if (act.action !== 'view' && !act.access) {
                // 如果有权限增删改等等，则有权限查看
                jn.actions = jn.actions.map(ele => {
                  if (ele.action === 'view' || ele.id === act.id) {
                    ele.access = true;
                  }
                  return ele;
                });
              } else {
                jn.actions = jn.actions.map(ele => {
                  if (act.id === ele.id) {
                    ele.access = !ele.access;
                  }
                  return ele;
                });
              }
            }
            return false;
          }
          return true;
        },
        // eslint-disable-next-line
        'children'
      );
      this.tableData = data;
    },

    /**
     * 正式提交之前，需要把所有access为false的action去掉
     */
    permissionsFilter(perms) {
      breadFirstTree(
        perms,
        jn => {
          if (!!jn.actions && Array.isArray(jn.actions)) {
            jn.actions = jn.actions.filter(ele => ele.access);
          }
          return true;
        },
        // eslint-disable-next-line
        'children'
      );
    },

    /**
     * 如果一个router的action为空，则它应该被过滤；
     * 另外，如果一个router有访问权限，那么和它permission相同并且hidden为true的路由都有访问权限
     */
    attachHiddenRouter(perms) {
      breadFirstTree(
        perms,
        jn => {
          if (Array.isArray(jn.children)) {
            for (let i = 0; i < jn.children.length; i) {
              const child = jn.children[i];
              if (Array.isArray(child.actions) && child.actions.length > 0) {
                // 上式说明是有权限访问的
                const meta = child.meta || '{}';
                const { permission } = JSON.parse(meta);
                if (permission) {
                  // 找到同路由组的其他路由，并插进children
                  const sortedPerm = permission.sort((a, b) => a.name.charCodeAt(0) - b.name.charCodeAt(0)).join(',');
                  if (this.routerGroup[sortedPerm]) {
                    const filteredRouterGroup = this.routerGroup[sortedPerm].filter(ele => {
                      const index = jn.children.findIndex(item => item.id === ele.id);
                      return ele.id !== child.id && index === -1;
                    });
                    jn.children.splice(i + 1, 0, ...filteredRouterGroup);
                    i += filteredRouterGroup.length + 1;
                  } else {
                    i++;
                  }
                } else {
                  i++;
                }
              } else if (Array.isArray(child.actions) && child.actions.length === 0) {
                jn.children.splice(i, 1);
              } else {
                i++;
              }
            }

            // for(let child of jn.children){
            //   if(Array.isArray(child.actions) && child.actions.length > 0){
            //     // 上式说明是有权限访问的
            //     const meta = child.meta || '{}';
            //     const { permission } = JSON.parse(meta);
            //     jn.children = jn.children.concat(this.findHiddenRouter(jn.id, permission));
            //   }
            // }
          }
          return true;
        },
        // eslint-disable-next-line
        'children'
      );
    },

    /**
     * 在originData中寻找hidden并且permission和siblingRoute一样的兄弟routes
     */
    findHiddenRouter(parentId, perm) {
      const routes = [];
      breadFirstTree(
        this.originData,
        jn => {
          if (jn.id === parentId) {
            for (const child of jn.children) {
              const meta = child.meta || '{}';
              const { hidden, permission } = JSON.parse(meta);
              if (hidden && JSON.stringify(permission) === JSON.stringify(perm)) {
                routes.push(child);
              } else {
                continue;
              }
            }
          }
          return true;
        },
        // eslint-disable-next-line
        'children'
      );
      return routes;
    },

    // 最终全页面提交
    handleSubmit() {
      const { validateFields, getFieldsValue } = this.form;
      this.confirmLoading = true;
      const fieldNames = this.$_asyncValidateMixin_fieldsFilter(getFieldsValue());
      validateFields(fieldNames, errors => {
        const { name, status, comment } = getFieldsValue();
        if (!errors) {
          const role = {
            id: this.id,
            name: name.trim(),
            status,
            comment: comment.trim(),
            appId: this.appId
          };
          const permissions = cloneDeep(this.tableData);
          this.permissionsFilter(permissions);
          this.attachHiddenRouter(permissions);
          if (this.formType === 1) {
            // 新增
            createRole({
              role,
              permissions
            })
              .then(res => {
                this.$message.success(res.message);
                this.$router.push({
                  name: 'roleList'
                });
              })
              .finally(() => {
                this.confirmLoading = false;
              });
          } else {
            // 编辑
            updateRole({
              role,
              permissions
            })
              .then(res => {
                this.visible = false;
                this.$message.success(res.message);
                this.$router.back();
              })
              .finally(() => {
                this.confirmLoading = false;
              });
          }
        } else {
          this.confirmLoading = false;
        }
      });
    },

    resetForm() {
      this.form.setFieldsValue({
        name: '',
        comment: ''
      });
      this.$_asyncValidateMixin_resetFields();
    }
  }
};
</script>

<style lang="less" scoped>
.card {
  margin-bottom: 24px;
}
</style>
